#include <iostream>
#include <vector>
#include <cstdlib>
#include "BossFight.h"
#include "Enemy.h"
#include "Game.h"
#include "Hero.h"
#include "Quest.h"
#include "Riddle.h"

using namespace std;

void Help(); //Segítség a program használatához.
void CreateBossVec(vector<Enemy>& enemies); //Az ellenfelek vektorának feltöltése.
void CreateQuestVec(vector<Quest*>& quests, vector<Enemy>& enemies, Hero* character); //A küldetések vektorának feltöltése.
void Destructor(vector<Quest*>& quests); //A küldetések vektorának törlése.
int IsNumber(string text); //Ellenőrzést elvégző függvény.

int main()
{
    //Létrehozzuk az "üres" objektumokat.
    vector<Enemy> enemies;
    vector<Quest*> quests;
    Hero* character = new Hero();

    //Feltöltjük az objektumokat.
    CreateQuestVec(quests, enemies, character);
    CreateBossVec(enemies);

    //A menü kiírása.
    int c = 0;
    do
    {
        cout << "*********************" << endl;
        cout << "Teldrassil megmentese" << endl;
        cout << "*********************" << endl;
        cout << "1 - Uj jatek kezdese" << endl;
        cout << "2 - Mentett allas betoltese" << endl;
        cout << "3 - Segitseg" << endl;
        cout << "0 - Kilepes" << endl;
        c = IsNumber(">>> ");

        switch(c)
        {
        case 1:
        {
            character->CreateChar(); //Új játék kezdésekor létrehozza a felhasználó a karakterét.
            Game start(0, quests); //A játék elindul a 0. küldetéstől.
            start.Run(); //Ciklikusan végrehajtódnak a küldetések, amíg valamelyik -1-be nem vezet.
            break;
        }
        case 2:
        {
            string fname;
            cout << "A mentett karakter neve: "; //Bekérjük az elmentett karakter nevét.
            cin >> fname;
            character->LoadCharacter(fname); //Betöltjük a karakter adatait.
            Game start1(character->GetCurrentQ(), quests); //Folytatódik a játék attól a küldetéstől, ahol abbamaradt.
            start1.Run();
            break;
        }
        case 3:
        {
            Help(); //A segítség kiírása.
            break;
        }
        }
    }
    while(c != 0);

    //A felhasznált tárterület felszabadítása.
    delete character;
    Destructor(quests);

    return 0;
}

//A küldetéseket tartalmazó vektor feltöltése.
void CreateQuestVec(vector<Quest*>& quests, vector<Enemy>& enemies, Hero* character)
{
    ifstream f;
    f.open("quests.dat");
    if(f.fail())
    {
        cout << "Hianyzik a quests.dat fajl." << endl;
        exit(1);
    }

    while(!(f.eof() && !f.fail()))
    {

        int type;
        f >> type;

        //Ha hibás a fájl szerkezete.
        if(f.fail() || f.eof() || !( 1<=type && type<=3 ))
        {
            cout << "Hibas a quests.dat fajl." << endl;
            exit(1);
        }

        //Ha valamelyik küldetésnél hibás annak szerkezete, akkor kitöröljük az egész eddig feltöltött vektort,
        //mert úgysem tudjuk használni, és kilépünk a programból.
        switch(type)
        {
        case 1:
        {
            Quest* newQ = new Quest(character);
            newQ->Read(f);
            if(!f.fail())
            {
                quests.push_back(newQ);
            }
            else
            {
                cout << "Hibas a quests.dat fajl." << endl;
                Destructor(quests);
                exit(1);
            }
            break;
        }
        case 2:
        {
            Quest* newR = new Riddle(character);
            newR->Read(f);
            if(!f.fail())
            {
                quests.push_back(newR);
            }
            else
            {
                cout << "Hibas a quests.dat fajl." << endl;
                Destructor(quests);
                exit(1);
            }
            break;
        }
        case 3:
        {
            Quest* newF;
            newF = new BossFight(character, enemies);
            newF->Read(f);
            if(!f.fail())
            {
                quests.push_back(newF);
            }
            else
            {
                cout << "Hibas a quests.dat fajl." << endl;
                Destructor(quests);
                exit(1);
            }
            break;
        }
        }
    }
    f.close();
}

//Az ellenségeket tartalmazó tömb feltöltése.
void CreateBossVec(vector<Enemy>& enemies)
{
    ifstream f;
    f.open("enemies.dat");
    if(f.fail())
    {
        cout << "Hianyzik az enemies.dat fajl." << endl;
        exit(1);
    }

    while(!(f.eof() && !f.fail()))
    {
        Enemy boss;
        boss.Read(f);
        if(!f.fail())
        {
            enemies.push_back(boss);
        }
        else
        {
            cout << "Hibas az enemies.dat fajl." << endl;
            exit(1);
        }
    }
    f.close();
}

//A küldetéseket tartalmazó tömb törlése.
void Destructor(vector<Quest*>& quests)
{
    while(quests.size() != 0)
    {
        quests.pop_back();
    }
}

//Segítség a program használatához.
void Help()
{
    cout << endl;
    cout << "A jatekban fejtoroket kell tobbe kevesbe sikeresen megoldani, es ellensegeket kell legyozni." << endl;
    cout << "Ekozben tapasztalati pontokat lehet gyujteni, es eleg tapasztalati pont eseten szintet lehet lepni, amivel valtoznak a karakter tulajdonsagai." << endl;
    cout << endl;
    cout << "A fomenu 1-es opcioja az uj jatek kezdese." << endl;
    cout << "Ekkor ki kell valasztani, hogy melyik kaszttal szeretnel jatszani (1, 2, 3 gombok segitsegevel), majd el kell nevezni a karaktert, " << endl;
    cout << "de csak az angol ABC kis es nagybetuit lehet hasznalni." << endl;
    cout << endl;
    cout << "A fomenu 2-es opcioja a mentett allas betoltese." << endl;
    cout << "Ekkor meg kell adni az elmentett karakter nevet." << endl;
    cout << endl;
    cout << "A fomenu 0-as opcioja a jatekbol valo kilepes." << endl;
    cout << endl;
    cout << "A kuldeteseknek tobb tipusa is van:" << endl;
    cout << "Az udvozlo szoveg tipus" << endl;
    cout << "Ekkor csak egy billentyut le kell utni, és folytatodik a jatek." << endl;
    cout << "Fejtoro tipus" << endl;
    cout << "Egy kerdesre kell valaszolni egy szammal." << endl;
    cout << "Ha a szam pontos, akkor jar a legtobb tapasztalati pont, ha az adott intervallumban benne van, akkor kevesebb, ha pedig " << endl;
    cout << "az intervallumban sincs benne, akkor jar a legkevesebb xp." << endl;
    cout << "Harc az ellenseggel" << endl;
    cout << "A jatek soran 3 ellenseggel kell megkuzdeni." << endl;
    cout << "Minel kevesebb kor alatt nyersz a csataban, annal tobb tapasztalati pontot kapsz!" << endl;
    cout << endl;
    cout << "Minden masodik kuldetes utan fel lesz ajanlva a mentes lehetosege, es eldontheted, hogy elsz-e vele." << endl;
    cout << endl;
}

//A bemeneti számokat ellenőrző függvény.
int IsNumber(string text)
{
    int number;
    bool wrong;
    string t;
    do
    {
        cout << text;
        cin >> number;
        wrong = cin.fail();
        if(cin.fail() || number < 0 || number > 3)
        {
            cout << "Kerlek egy egesz szamot irj be 0 es 3 kozott!" << endl;
            cin.clear();
        }
        getline(cin, t);
    }
    while(wrong);
    return number;
}
